package ex;

import java.util.Arrays;
import java.util.Objects;

/**
 * @Description 二元序列偶
 * @Date 2022/3/19 21:22
 * @Author eric ling
 */
public class BinSeqPairs {
    private int length; // 二元序列偶的长度
    private int[] x;
    private int[] y;

    public BinSeqPairs(int length, int[] x, int[] y) {
        this.length = length;
        this.x = Arrays.copyOf(x, length);
        this.y = Arrays.copyOf(y, length);
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public int[] getX() {
        return x;
    }

    public void setX(int[] x) {
        this.x = x;
    }

    public int[] getY() {
        return y;
    }

    public void setY(int[] y) {
        this.y = y;
    }

    /**
     * 判断当前二元序列偶是否为二值自相关二元序列偶
     *
     * @return 是否为二值自相关二元序列偶
     */
    public boolean isBinomial() {
        return Arrays.stream(correlation()).distinct().count() == 2;
    }

    /**
     * 计算二元序列偶的自相关函数值
     *
     * @return 自相关函数值（不同步长对应相应索引）
     */
    public long[] correlation() {
        long[] rs = new long[length]; // 存放不同step对应的自相关函数值
        for (int step = 0; step < length; step++) {
            long sum = 0;
            for (int i = 0; i < length; i++) {
                sum += (long) x[i] * y[(i + step) % length];
            }
            rs[step] = sum;
        }
        return rs;
    }

    /**
     * @return 返回二元序列偶对应的差集偶
     */
    public DiffSetPair getDiffSetPair() {
        int[] k1Set = ArrayHandler.parse(x);
        int[] k2Set = ArrayHandler.parse(y);
        // 计算e
        int e = 0;
        int[] eSetWithTail = new int[length];
        for (int i = 0; i < x.length; i++) {
            if (x[i] + y[i] == 2) {
                eSetWithTail[e++] = i;
            }
        }
        // lambda = ((k1 * k2) - e) / (v - 1);
        DiffSetPair dsp = new DiffSetPair(length, k1Set.length, k2Set.length, e, ((k1Set.length * k2Set.length) - e) / (length - 1));
        dsp.setK1Set(k1Set);
        dsp.setK2Set(k2Set);
        dsp.seteSet(Arrays.copyOf(eSetWithTail, e));
        return dsp;
    }


    @Override
    public String toString() {
        return "ex.BinSeqPairs{" + "length=" + length + ", x=" + Arrays.toString(x) + ", y=" + Arrays.toString(y) + '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BinSeqPairs that = (BinSeqPairs) o;
        return length == that.length && Arrays.equals(x, that.x) && Arrays.equals(y, that.y);
    }

    @Override
    public int hashCode() {
        int result = Objects.hash(length);
        result = 31 * result + Arrays.hashCode(x);
        result = 31 * result + Arrays.hashCode(y);
        return result;
    }

    public static void main(String[] args) {
        int[] x = new int[]{-1, -1, 1, 1, -1, 1, -1};
        int[] y = new int[]{0, 0, 1, 1, 0, 1, 0};
        BinSeqPairs binSeqPairs = new BinSeqPairs(x.length, x, y);
        System.out.println(Arrays.toString(binSeqPairs.correlation())); // [14, 11, 11]
        System.out.println(binSeqPairs.isBinomial()); // true
        System.out.println(binSeqPairs.getDiffSetPair()); // ex.DiffSetPair{v=13, k1=6, k2=7, e=6, lambda=3, vSet=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], k1Set=[1, 3, 4, 9, 10, 12], k2Set=[0, 1, 3, 4, 9, 10, 12], eSet=null}
    }
}
